use crate::db::config::DB_CONFIG;
use once_cell::sync::Lazy;
use sea_orm::{ActiveModelTrait, Database, DatabaseConnection, EntityTrait};
use crate::error::{AppError, Result};
use std::collections::HashMap;
use std::path::Path;
use std::sync::Mutex; // 确保 AppError 和 Result 已定义

// 使用 Lazy 和 Mutex 来安全地管理多个数据库连接
static DB_CONNECTIONS: Lazy<Mutex<HashMap<String, DatabaseConnection>>> =
    Lazy::new(|| Mutex::new(HashMap::new()));

/// 初始化指定路径的数据库。
/// 如果数据库文件不存在，则会尝试创建它及其父目录。
/// 会为该数据库连接创建 'items' 表（如果尚不存在）。
///
/// # Arguments
/// * `db_identifier`: 用于在内部 HashMap 中唯一标识此数据库连接的字符串。
/// * `db_url`: SQLite 数据库的连接字符串 (例如, "sqlite:/path/to/your/db_name.db?mode=rwc").
///             建议使用 `?mode=rwc` (read-write-create) 来确保文件被创建。
async fn setup_database(db_identifier: &str, db_url: &str) -> Result<()> {
    // 检查数据库文件目录是否存在，如果不存在则创建
    // 从 "sqlite:" 前缀移除，获取文件路径
    let path_str = db_url.trim_start_matches("sqlite:");
    let db_path = Path::new(path_str.split('?').next().unwrap_or(path_str)); // 处理可能存在的查询参数

    if let Some(parent_dir) = db_path.parent() {
        if !parent_dir.to_string_lossy().is_empty() && !parent_dir.exists() {
            // 确保父目录不是根目录或空
            std::fs::create_dir_all(parent_dir)?;
            log::info!(
                "[{}] Created database directory: {:?}",
                db_identifier,
                parent_dir
            );
        }
    }

    // 创建数据库连接
    let conn = Database::connect(db_url).await.map_err(|db_err| {
        log::error!(
            "[{}] Failed to connect to database ({}): {}",
            db_identifier,
            db_url,
            db_err
        );
        db_err
    })?;
    log::info!(
        "[{}] Successfully connected to database: {}",
        db_identifier,
        db_url
    );

    // 将连接存储到全局 HashMap 中
    let mut connections = DB_CONNECTIONS
        .lock()
        .map_err(|_| AppError::Custom("Failed to lock DB_CONNECTIONS".to_string()))?;
    connections.insert(db_identifier.to_string(), conn);
    log::info!("[{}] Database connection stored.", db_identifier);

    Ok(())
}

/// 获取指定标识符的数据库连接的克隆。
///
/// # Arguments
/// * `db_identifier`: `setup_database` 时使用的数据库标识符。
///
/// # Returns
/// * `Result<DatabaseConnection>`: 成功时返回克隆的数据库连接，否则返回错误。
pub fn get_connection(db_identifier: &str) -> Result<DatabaseConnection> {
    let connections = DB_CONNECTIONS
        .lock()
        .map_err(|_| AppError::Custom("Failed to lock DB_CONNECTIONS for get".to_string()))?;
    connections.get(db_identifier).cloned().ok_or_else(|| {
        AppError::InitError(format!(
            "Database '{}' not initialized or found. Call setup_database first.",
            db_identifier
        ))
    })
}



pub async fn create<Entity, ActiveModel, Model>(
    db_identifier: &str,
    active_model: ActiveModel,
) -> Result<Model, AppError>
where
    Entity: EntityTrait<Model = Model>,
    ActiveModel: ActiveModelTrait<Entity = Entity> + Send + 'static + sea_orm::ActiveModelBehavior,
    Model: std::marker::Send + 'static + sea_orm::IntoActiveModel<ActiveModel>,
{
    let db = get_connection(db_identifier)?;
    let res = active_model.insert(&db).await;
    match res {
        Ok(model) => Ok(model),
        Err(e) => Err(AppError::Custom(format!("Failed to create record: {:?}", e))),
    }
}

pub async fn initialize_databases() {
    for config_item in DB_CONFIG.iter() {
        let identifier = config_item.tag;
        let path = config_item.url;
        // 构建完整的数据库 URL
        let db_url = format!("sqlite:{}?mode=rwc", path);
        log::info!(
            "Initializing database: identifier='{}', url='{}'",
            identifier,
            db_url
        );
        // 调用 setup_database 进行设置
        if let Err(e) = setup_database(identifier, &db_url).await {
            log::error!("Failed to setup database '{}': {:?}", identifier, e);
        } else {
            log::info!("Successfully setup database '{}'", identifier);
        }
    }
}
